#include "json.h"

/**
 * Takes the given name and alarmname and converts it to a JSON alarm object in the string.
 * The string must be at least ??? long.
 * Returns amount of chars written.
 */
int createAlarmJson(char sensorName[], char alarmName[], char string[]) {
	int stringIndex = 0;
	stringIndex += sprintf(&string[stringIndex], "{");
	stringIndex += sprintf(&string[stringIndex], "\"alarm\":");
	stringIndex += sprintf(&string[stringIndex], "{");
	stringIndex += sprintf(&string[stringIndex], "\"name\":\"%s\",", sensorName);
	stringIndex += sprintf(&string[stringIndex], "\"alarmName\":\"%s\",", alarmName);
	stringIndex += sprintf(&string[stringIndex], "}");
	stringIndex += sprintf(&string[stringIndex], "}");
	return stringIndex;
}

/**
 * Takes the given sensor arrays and converts it to a JSON object in the string.
 * The string must be at least ??? long per analog sensor, ??? per binary sensor + some extra.
 * Returns amount of chars written.
 */
int sensorsToJson(struct AnalogSensor analogSensors1[], int amountOfAnalogSensors1, struct AnalogSensor analogSensors2[], int amountOfAnalogSensors2,
		struct BinarySensor binarySensors[], int amountOfBinarySensors, char string[]) {
	int stringIndex = 0;
	int i;
	stringIndex += sprintf(&string[stringIndex], "{");
	stringIndex += analogSensorsToJsonArray(analogSensors1, amountOfAnalogSensors1, analogSensors2, amountOfAnalogSensors2, &string[stringIndex]);
	stringIndex += sprintf(&string[stringIndex], ",");
	stringIndex += binarySensorsToJsonArray(binarySensors, amountOfBinarySensors, &string[stringIndex]);
	stringIndex += sprintf(&string[stringIndex], "}\n");
	return stringIndex;
}

/**
 * Takes the given sensor array and converts it to a JSON array in the string.
 * The string must be at least ??? long per sensor + some extra.
 * Returns amount of chars written.
 */
int analogSensorsToJsonArray(struct AnalogSensor sensors[],
		int amountOfSensors, struct AnalogSensor sensors2[], int amountOfSensors2, char string[]) {
	int stringIndex = 0;
	int i;
	stringIndex += sprintf(&string[stringIndex], "\"analogSensors\":[");
	for (i = 0; i < amountOfSensors; i++) {
		stringIndex += analogSensorToJson(&sensors[i], &string[stringIndex]);
		stringIndex += sprintf(&string[stringIndex], ",");
	}
	for (i = 0; i < amountOfSensors2; i++) {
		stringIndex += analogSensorToJson(&sensors2[i], &string[stringIndex]);
		stringIndex += sprintf(&string[stringIndex], ",");
	}
	stringIndex += sprintf(&string[stringIndex-1], "]"); // Overwrite final comma
	stringIndex -= 1; // Because of overwritten comma, decrement the index;
	return stringIndex;
}

/**
 * Takes the given sensor array and converts it to a JSON array in the string.
 * The string must be at least ??? long per sensor + some extra.
 * Returns amount of chars written.
 */
int binarySensorsToJsonArray(struct BinarySensor sensors[],
		int amountOfSensors, char string[]) {
	int stringIndex = 0;
	int i;
	//stringIndex += sprintf(&string[stringIndex], "{");
	stringIndex += sprintf(&string[stringIndex], "\"binarySensors\":[");
	for (i = 0; i < amountOfSensors; i++) {
		stringIndex += binarySensorToJson(&sensors[i], &string[stringIndex]);
		if (i < amountOfSensors - 1) {
			// Comma only necessary if its not the last one in the array
			stringIndex += sprintf(&string[stringIndex], ",");
		}
	}
	stringIndex += sprintf(&string[stringIndex], "]");
	//stringIndex += sprintf(&string[stringIndex], "}");
	return stringIndex;
}

/**
 * Takes the given sensor and converts it to a JSON object in the string.
 * The string must be at least ??? long.
 * Returns amount of chars written.
 */
int analogSensorToJson(struct AnalogSensor *sensor, char string[]) {
	int index = 0;
	index += sprintf(&string[index], "{");
	index += sprintf(&string[index], "\"name\":\"%s\",", sensor->name);
	index += sprintf(&string[index], "\"type\":\"Analog\",");
	index += sprintf(&string[index], "\"value\":%lf,", sensor->value);
	index += sprintf(&string[index], "\"unit\":\"%s\",", sensor->unit);
	index += sprintf(&string[index], "\"timeStamp\":\"%s\",",
			sensor->timeStamp);
	index += sprintf(&string[index], "\"lowerLimit\":%lf,",
			sensor->lowerLimit);
	index += sprintf(&string[index], "\"upperLimit\":%lf,",
			sensor->upperLimit);
	index += sprintf(&string[index], "\"lowerLimitAlarmName\":\"%s\",",
			sensor->lowerLimitAlarmName);
	index += sprintf(&string[index], "\"upperLimitAlarmName\":\"%s\"",
			sensor->upperLimitAlarmName);
	index += sprintf(&string[index], "}");
	return index;
}

/**
 * Takes the given sensor and converts it to a JSON object in the string.
 * The string must be at least ??? long.
 * Returns amount of chars written.
 */
int binarySensorToJson(struct BinarySensor *sensor, char string[]) {
	int index = 0;
	index += sprintf(&string[index], "{");
	index += sprintf(&string[index], "\"name\":\"%s\",", sensor->name);
	index += sprintf(&string[index], "\"type\":\"Binary\",");
	index += sprintf(&string[index], "\"value\":\"%s\",",
			sensor->value == 0 ? "false" : "true");
	index += sprintf(&string[index], "\"timeStamp\":\"%s\",",
			sensor->timeStamp);
	index += sprintf(&string[index], "\"alarmname\":\"%s\"",
			sensor->alarmName);
	index += sprintf(&string[index], "}");
	return index;
}

/**
 * Returns 0 if it failed to parse.
 * Returns 1 if it parsed an analog change.
 * Returns 2 if it parsed a binary change.
 */
int parseAlarmChangeJson(char * jsonString, struct AnalogAlarmChangeStruct *analogChangeStruct, struct BinaryAlarmChangeStruct *binaryChangeStruct) {
	struct cJSON *totalJsonStruct; // Need to keep this around because it needs to be freed.
	struct cJSON *tempStruct;
	char nameString[41];

	puts("Parsing JSON obj:\n");
	puts(jsonString);

	totalJsonStruct = cJSON_Parse(jsonString);
	if (totalJsonStruct == 0) {
		puts("JSON parse error");
		return 0;
	}
	if (totalJsonStruct->child == 0) {
		puts("JSON format error");
		return 0;
	}

	if (strcmp(totalJsonStruct->child->string, "analogAlarmChange") == 0) {
		puts("JSON is analogAlarmChange");

		// Get the value of the sensorname object
		strcpy(nameString, "sensorname");
		tempStruct = cJSON_GetObjectItem(totalJsonStruct->child, nameString);
		strcpy(analogChangeStruct->name, tempStruct->valuestring);
		printf("Name=%s\n", analogChangeStruct->name);

		// Get the value of the lower limit
		strcpy(nameString, "lowerboundary");
		tempStruct = cJSON_GetObjectItem(totalJsonStruct->child, nameString);
		analogChangeStruct->lowerLimit = tempStruct->valuedouble;
		printf("Lowerlimit=%f\n", analogChangeStruct->lowerLimit);

		// Get the value of the lower limit
		strcpy(nameString, "upperboundary");
		tempStruct = cJSON_GetObjectItem(totalJsonStruct->child, nameString);
		analogChangeStruct->upperLimit = tempStruct->valuedouble;
		printf("Upperlimit=%f\n", analogChangeStruct->upperLimit);

		fflush(stdout);
		cJSON_Delete(totalJsonStruct);
		return 1;
	} else if ((strcmp(totalJsonStruct->child->string, "binaryAlarmChange") == 0)) {
		puts("JSON is binaryAlarmChange");

		// Get the value of the sensorname object
		strcpy(nameString, "sensorname");
		tempStruct = cJSON_GetObjectItem(totalJsonStruct->child, nameString);
		strcpy(binaryChangeStruct->name, tempStruct->valuestring);
		printf("Name=%s\n", binaryChangeStruct->name);

		// Get the value of the alarm
		strcpy(nameString, "alarm");
		tempStruct = cJSON_GetObjectItem(totalJsonStruct->child, nameString);
		if (strcmp(tempStruct->valuestring, "yes")) {
			strcpy(binaryChangeStruct->alarmName, tempStruct->valuestring);
		} else if (strcmp(tempStruct->valuestring, "no")) {
			strcpy(binaryChangeStruct->alarmName, "no alarm");
		} else {
			puts("Failed to successfully parse binary alarm change");
			fflush(stdout);
			cJSON_Delete(totalJsonStruct);
			return 0;
		}

		fflush(stdout);
		cJSON_Delete(totalJsonStruct);
		return 2;
	} else {
		puts("JSON format is unknown");
		fflush(stdout);
		cJSON_Delete(totalJsonStruct);
		return 0;
	}
}
